"use strict";
// https://egonelbre.com/js/gopher/
if (window.animationLoop) {
	window.cancelAnimationFrame(window.animationLoop)
}
// 颜色
class HSL {
	constructor(h, s, l) {
		this.h = h
		this.s = s
		this.l = l
	}

	toString() {
		return "hsl(" +
			(this.h * 360).toFixed(2) + "," +
			(this.s * 100).toFixed(2) + "%," +
			(this.l * 100).toFixed(2) + "%)";
	}
}

const tau = Math.PI * 2

	let gopher = {
		body: new HSL(205.0 / 360, 1.0, 0.81),
		bodyDark: new HSL(205.0 / 360, 0.55, 0.71),
		dark: new HSL(217.0 / 360, 0.19, 0.18),
		light: new HSL(217.0 / 360, 0.0, 1.00),
		lightDark: new HSL(217.0 / 360, 0.0, 0.90),
		limb: new HSL(46.0 / 360, 0.38, 0.80),

		head: { x: 0, y: 0 },
		gaze: { x: 0, y: 0 },
	};
	let view2 
	export function close(){
		view2.onmousemove=()=>{}
		window.removeEventListener('resize', updateViewSize);
	}
	let view ; let context  
export function start() {

view =document.getElementById("view")	
context=view.getContext("2d")
	updateViewSize()
	
	window.animationLoop = tick();
	
	window.addEventListener("resize", updateViewSize)
	
	view2= document.querySelector("body")

	view2.onmousemove=(ev) => {
		gopher.gaze.x = (ev.clientX * 2.0 / view.width - 1)-(view.offsetLeft/view.width/1.5)
		gopher.gaze.y = (ev.clientY * 4.0 / view.height - 1)-(view.offsetTop/view.height/3.5);   
		gopher.head.x = gopher.gaze.x * 0.5;
		gopher.head.y = gopher.gaze.y * 0.5;
		ev.preventDefault()
	}

	// view2.addEventListener("touchmove", (ev) => {
	//  if(ev.targetTouches.length == 0) return;

	//  // let screenSize = {x: view.width, y: view.height}
	//  let touch = ev.targetTouches[0]

	//  gopher.gaze.x = touch.clientX * 2.0 / view.width - 1;
	//  gopher.gaze.y = touch.clientY * 2.0 / view.height - 1;

	//  gopher.head.x = gopher.gaze.x * 0.5;
	//  gopher.head.y = gopher.gaze.y * 0.5;

	//  ev.preventDefault()
	// });






	
	
}
		function updateViewSize() {
			view.width = window.innerWidth
			view.height = window.innerHeight
	
			//  view.width = view.clientWidth;
			//  view.height = view.clientHeight;
		}
		function tick() {
			context.clearRect(0, 0, 10000, 10000);
			context.save()
	
			// context.fillStyle = "#000";
			// context.fillText(stringify(gopher.head), 20, 20)
			// context.fillText(stringify(gopher.gaze), 20, 30)
	
			let screenSize = { x: view.width, y: view.height }
			render(gopher, context, screenSize)
			context.restore()
			return window.requestAnimationFrame(tick)
		}
	
		// function stringify(v) {
		//  return JSON.stringify(v, (key, val) => {
		//   if(typeof val == "number"){
		//    return val.toFixed(2)
		//   }
		//   return val
		//  })
		// }
		function headOffset(gopher, eye, bodyRadius) {
			let x = eye * bodyRadius * 0.65
			let y = -bodyRadius * 1.1
	
			x += Math.sin(gopher.head.x - eye * 0.4) * bodyRadius * 0.3
			y += Math.sin(gopher.head.y * tau / 4) * bodyRadius * 0.15
	
			return { x: x, y: y }
		}
	
		function saved(draw, fn) {
			draw.save()
			fn(draw)
			draw.restore()
		}
		function render(gopher, draw, screenSize) {
		let bodyRadius = Math.min(screenSize.x, screenSize.y) / 2
		bodyRadius *= 0.8

		let eyeRadius = bodyRadius * 0.4
		let earRadius = eyeRadius * 0.53
		let lineWidth = bodyRadius * 0.045
		let highlightSize = eyeRadius * 0.06

		draw.lineWidth = lineWidth
		draw.strokeStyle = gopher.dark.toString()

		// The center of the drawing is in the bottom-middle.
		draw.translate(screenSize.x / 2, screenSize.y)

		for (let ear = -1; ear <= 1; ear += 2) {
			saved(draw, (draw) => { // ear
				let earOffset = headOffset(gopher, -ear, bodyRadius)
				earOffset.x *= -1
				earOffset.x += ear * earRadius * 0.3
				earOffset.y = -bodyRadius * 1.8 - Math.sin(gopher.head.y) * earRadius * 0.5

				draw.translate(earOffset.x, earOffset.y)
				draw.scale(ear, 1)
				draw.rotate(tau / 10)
				draw.translate(0, earRadius)

				let earPath = new Path2D()

				earPath.moveTo(-earRadius, earRadius)
				earPath.lineTo(-earRadius, -earRadius)
				earPath.bezierCurveTo(
					-earRadius, -earRadius - earRadius * 1.3,
					earRadius, -earRadius - earRadius * 1.3,
					earRadius, -earRadius)
				earPath.lineTo(earRadius, earRadius)

				draw.fillStyle = gopher.body.toString()
				draw.fill(earPath)
				draw.stroke(earPath)

				let earInline = new Path2D()
				earInline.moveTo(0, 0)
				earInline.quadraticCurveTo(
					-earRadius * 0.6, -earRadius,
					earRadius * 0.2, -earRadius * 1.4
				);
				earInline.moveTo(0, 0)
				earInline.quadraticCurveTo(
					-earRadius * 0.6, -earRadius,
					earRadius * 0.3, -earRadius * 1.0
				);

				draw.lineWidth = lineWidth * 0.7
				draw.lineCap = "round"
				draw.stroke(earInline)
			})
		}

		saved(draw, (draw) => { // body
			let bodyPath = new Path2D()

			bodyPath.moveTo(-bodyRadius, 0)
			bodyPath.lineTo(-bodyRadius, -bodyRadius)
			bodyPath.bezierCurveTo(
				-bodyRadius, -bodyRadius - bodyRadius * 1.2,
				bodyRadius, -bodyRadius - bodyRadius * 1.2,
				bodyRadius, -bodyRadius)
			bodyPath.lineTo(bodyRadius, 0)

			draw.fillStyle = gopher.bodyDark.toString()
			draw.fill(bodyPath)
			saved(draw, (draw) => {
				draw.clip(bodyPath)
				draw.translate(bodyRadius * 0.1, 0)
				draw.fillStyle = gopher.body.toString()
				draw.fill(bodyPath)
			})
			draw.stroke(bodyPath)
		})

		for (let eye = -1; eye <= 1; eye += 2) {
			let gaze = gopher.gaze;

			saved(draw, (draw) => { // eye
				let eyeOffset = headOffset(gopher, eye, bodyRadius);
				draw.translate(eyeOffset.x, eyeOffset.y);

				let eyePath = new Path2D();
				eyePath.arc(0, 0, eyeRadius, 0, tau, true);

				draw.fillStyle = gopher.lightDark.toString()
				draw.fill(eyePath)

				saved(draw, (draw) => {
					draw.clip(eyePath)
					draw.translate(eyeRadius * 0.2, -eyeRadius * 0.15)
					draw.fillStyle = gopher.light.toString()
					draw.fill(eyePath)
				})

				draw.stroke(eyePath)

				let pupil = { x: gaze.x, y: gaze.y }
				let mag = Math.sqrt(pupil.x * pupil.x + pupil.y * pupil.y)
				if (mag > 1) {
					pupil.x /= mag + 0.0001;
					pupil.y /= mag + 0.0001;
				}
				pupil.x = Math.sin(pupil.x + eye * 0.4) * eyeRadius * 0.6
				pupil.y = Math.sin(pupil.y) * eyeRadius * 0.6
				let pupilSize = eyeRadius * 0.25

				let pupilPath = new Path2D();
				pupilPath.arc(pupil.x, pupil.y, pupilSize, 0, tau, true)
				draw.fillStyle = gopher.dark.toString()
				draw.fill(pupilPath)

				// pupil highlight
				let highlighPath = new Path2D()
				highlighPath.arc(
					pupil.x + pupilSize * 0.3 - gaze.x * highlightSize * 0.3,
					pupil.y - pupilSize * 0.3 - gaze.y * highlightSize * 0.3, highlightSize, 0, tau, true)
				draw.fillStyle = gopher.light.toString()
				draw.fill(highlighPath)
			})
		}

		saved(draw, (draw) => { // nose
			let tipSize = eyeRadius * 0.2;
			let toothSize = tipSize;
			let noseSize = tipSize * 2.2;

			let noseOffset = headOffset(gopher, 0, bodyRadius)
			noseOffset.y += eyeRadius * 0.8;
			draw.translate(noseOffset.x, noseOffset.y);

			saved(draw, (draw) => { // tooth
				draw.translate(0, tipSize * 1.2 - gopher.head.y * tipSize * 0.3)
				draw.beginPath()
				draw.moveTo(-toothSize, 0)
				draw.lineTo(-toothSize, toothSize * 1.5)
				draw.bezierCurveTo(
					-toothSize, toothSize * 2,
					toothSize, toothSize * 2,
					toothSize, toothSize * 1.5,
				)
				draw.lineTo(toothSize, 0)
				draw.fillStyle = gopher.light.toString()
				draw.fill()
				draw.lineWidth = lineWidth * 0.7;
				draw.stroke()
			})

			saved(draw, (draw) => { // nose
				draw.translate(0, tipSize * 1.2)
				draw.beginPath()

				draw.moveTo(-noseSize, 0)
				draw.bezierCurveTo(
					-noseSize, -noseSize,
					noseSize, -noseSize,
					noseSize, 0
				)
				draw.bezierCurveTo(
					noseSize, noseSize * 0.4,
					-noseSize, noseSize * 0.4,
					-noseSize, 0
				)
				draw.closePath()

				draw.fillStyle = gopher.limb.toString()
				draw.fill()
				draw.stroke()
			})

			saved(draw, (draw) => { // tip of the nose
				let tip = {
					x: Math.sin(gopher.head.x) * tipSize,
					y: Math.sin(gopher.head.y) * tipSize * 0.5 - tipSize * 0.2,
				};

				draw.beginPath()
				draw.scale(1.2, 0.9)
				draw.arc(tip.x, tip.y, tipSize, 0, tau, true)
				draw.fillStyle = gopher.dark.toString()
				draw.fill()

				// tip highlight
				draw.beginPath()
				draw.arc(
					tip.x + tipSize * 0.3 - gopher.head.x * highlightSize * 0.3,
					tip.y - tipSize * 0.3 - gopher.head.y * highlightSize * 0.3, highlightSize, 0, tau, true)
				draw.fillStyle = gopher.light.toString()
				draw.fill()
			})
		})
	}
